Skip to content

Minecraft: run the server as the letsbuilda user - #28

Merged
shenanigansd merged 2 commits into
mainfrom
claude/docker-minecraft-user-id-s647ne
Aug 30, 2026
Merged

Minecraft: run the server as the letsbuilda user#28
shenanigansd merged 2 commits into
mainfrom
claude/docker-minecraft-user-id-s647ne

Conversation

@shenanigansd

Copy link
Copy Markdown
Member

What

Run the Minecraft container as the letsbuilda host account instead of the itzg image's default UID/GID 1000, without hardcoding the numeric ID anywhere in the repo.

  • The minecraft role now looks up the account at deploy time (ansible.builtin.getent on passwd/letsbuilda — read-only, fails fast if the account is missing) and writes the IDs to /opt/letsbuilda/minecraft/.env.
  • compose.yaml sets user: "${UID:?}:${GID:?}", interpolated by docker compose from that .env (docker_compose_v2 picks it up from project_src automatically). The :? makes a missing .env fail the deploy loudly instead of silently falling back to the image default.

Why

/opt/letsbuilda/minecraft/ is owned by letsbuilda, but the image was running the server as its built-in default (1000), so world data ended up owned by the wrong user.

With the compose user: directive the container starts as letsbuilda from the first process — the image's root entrypoint/step-down machinery is skipped entirely, no root process ever exists in the container, and nothing can chown the bind mount. (/data ownership was already fixed on the host; the alternative UID/GID env-var mode would instead keep a root entrypoint that auto-chowns /data, trading the rootless property for self-healing ownership.)

compose.yaml stays a plain static file at the same path, so the Dependabot docker-compose watcher keeps bumping the pinned image.

Validation

  • check-yaml, yamlfix, and whitespace hooks pass on the changed files
  • ansible-playbook --syntax-check and ansible-lint pass clean (production profile)

Deploy notes

  • One-time container recreation on the next playbook run (service config changed).
  • docker inspect --format '{{.Config.User}}' should show 1001:1001, and the java process runs as letsbuilda from startup.
  • A bare docker compose exec shell now runs as the unnamed UID (I have no name! prompt) — cosmetic and expected.
  • Any future /data ownership drift (restored backup, files copied in as root) is a manual chown -R letsbuilda:letsbuilda, since the container can no longer fix ownership itself.

🤖 Generated with Claude Code

https://claude.ai/code/session_01NoJDrw76ZHLTcBG8JTWW2c


Generated by Claude Code

claude added 2 commits August 30, 2026 04:50
The itzg image defaults to UID/GID 1000, but /opt/letsbuilda/minecraft
is owned by letsbuilda, so world data ended up owned by the wrong user.

Look up the letsbuilda account's UID/GID at deploy time with getent and
write them to the compose project's .env, which docker compose reads for
${UID:?}/${GID:?} interpolation into the container environment. The
image's entrypoint then chowns /data and drops privileges to that user
on startup. No numeric ID is hardcoded, and compose.yaml stays a plain
static file so Dependabot keeps bumping the pinned image.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NoJDrw76ZHLTcBG8JTWW2c
Run the whole container as letsbuilda from the start rather than having
the image's root entrypoint step down: no root process ever exists in
the container, and nothing can chown the bind mount behind our back.
/data ownership was already fixed on the host, and any future drift is
a manual chown. The getent-to-.env lookup is unchanged; compose now
interpolates the IDs into user: instead of the container environment.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NoJDrw76ZHLTcBG8JTWW2c
@shenanigansd
shenanigansd requested a review from a team as a code owner August 30, 2026 04:58
@shenanigansd
shenanigansd merged commit cdbadcf into main Aug 30, 2026
5 checks passed
@shenanigansd
shenanigansd deleted the claude/docker-minecraft-user-id-s647ne branch August 30, 2026 04:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants